package de.slash.jplaylistextractor;

import de.slash.jplaylistextractor.common.Constants;
import de.slash.jplaylistextractor.common.ExceptionHandler;
import de.slash.jplaylistextractor.common.PlaylistExtractorLogger;
import de.slash.jplaylistextractor.model.Media;
import de.slash.jplaylistextractor.utils.FileCopier;
import info.clearthought.layout.TableLayout;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.ResourceBundle;
import java.util.logging.Logger;

/**
 * User: Slash
 * Date: 24.02.2012
 * Time: 14:58
 */
public class AppMain
{
    private static JTextField playlistField;
    private static JFrame frame;
    private static PlaylistExtractorTableModel tableModel;
    private static JTextField outputField;
    private static JTable table;
    private static JProgressBar progressBar;
    private final static Logger logger = Logger.getLogger(AppMain.class.getName());
    private static ResourceBundle resourceBundle;
    private static ExceptionHandler exceptionHandler;

    public static void main(String[] args)
    {
        try
        {
            PlaylistExtractorLogger.setup();
        }
        catch (IOException e)
        {
            throw new RuntimeException("Problems with creating the log files");
        }

        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        try
        {
            resourceBundle = ResourceBundle.getBundle("PlaylistExtractor");
            frame = new JFrame();
            exceptionHandler = new ExceptionHandler(logger, resourceBundle, frame);

            JPanel panel = new JPanel();

            double size[][] = {{20, TableLayout.FILL, 20, 20}, {20, 20, 20, 20, TableLayout.FILL, 20, 20, 20, 20, 20, 20, 20, 20}};
            TableLayout layout = new TableLayout(size);
            panel.setLayout(layout);
            panel.setBackground(Color.WHITE);
            JLabel playlistLabel = new JLabel(resourceBundle.getString("Playlist"));
            panel.add("1,1", playlistLabel);

            playlistField = new JTextField();
            playlistField.addFocusListener(new TextFieldFocusListener(playlistField));
            panel.add("1,2", playlistField);

            JButton playlistButton = new JButton();
            playlistButton.setIcon(new ImageIcon(ImageIO.read(AppMain.class.getResourceAsStream(Constants.ICON_SEARCH))));

            tableModel = new PlaylistExtractorTableModel(0,2 );
            table = new JTable(tableModel);
            table.getColumnModel().getColumn(0).setCellRenderer(new BooleanCellRenderer());
            table.getColumnModel().getColumn(0).setCellEditor(new BooleanCellEditor());

            table.setTableHeader(null);
            table.setDefaultRenderer(Object.class, new PlaylistExtractorTableCellRenderer());
            table.setShowHorizontalLines(false);
            table.setShowVerticalLines(false);

            table.getColumnModel().getColumn(0).setMinWidth(20);
            table.getColumnModel().getColumn(0).setMaxWidth(20);

            JScrollPane scrollPane = new JScrollPane(table);
            scrollPane.getViewport().setBackground(Color.WHITE);
            panel.add("1,4,2,4", scrollPane);
            progressBar = new JProgressBar();
            progressBar.setStringPainted(true);
            progressBar.setBackground(Color.WHITE);
            progressBar.setForeground(Constants.BLUE);

            panel.add("1,11, 2,11", progressBar);

            playlistButton.addActionListener(new PlaylistButtonActionListener());

            panel.add("2,2", playlistButton);
            JLabel outputLabel = new JLabel(resourceBundle.getString("Output"));
            panel.add("1,6", outputLabel);
            outputField = new JTextField();
            panel.add("1,7", outputField);

            outputField.addFocusListener(new TextFieldFocusListener(outputField));

            JButton outputButton = new JButton();
            outputButton.setIcon(new ImageIcon(ImageIO.read(AppMain.class.getResourceAsStream(Constants.ICON_SEARCH))));
            outputButton.addActionListener(new FileChooserButtonActionListener(outputField));
            panel.add("2,7", outputButton);

            JButton startButton = new JButton("Start");
            startButton.addActionListener(new StartButtonActionListener());
            panel.add("1,9, 2,9", startButton);

            frame.add(panel);
            frame.setLocationRelativeTo(null);
            frame.setIconImage(ImageIO.read(AppMain.class.getResourceAsStream(Constants.ICON_APPLICATION)));
            frame.setTitle(Constants.APPLICATION_TITLE);
            frame.setSize(500, 470);
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
        catch (Exception e)
        {
            exceptionHandler.handleException(e);
        }
    }

    static class TextFieldFocusListener implements FocusListener
    {
        private JTextField textField;

        TextFieldFocusListener(JTextField pTextField)
        {
            textField = pTextField;
        }

        public void focusGained(FocusEvent e)
        {
            if (textField.getBackground().equals(Color.WHITE))
            {
                textField.setBorder(BorderFactory.createCompoundBorder(Constants.GREY_BORDER, Constants.BLUE_BORDER));
            }
            else if (textField.getBackground().equals(Constants.LIGHT_RED))
            {
                textField.setBorder(BorderFactory.createCompoundBorder(Constants.GREY_BORDER, Constants.RED_BORDER));
            }
        }

        public void focusLost(FocusEvent e)
        {
            textField.setBorder(Constants.GREY_BORDER);
        }
    }

    static class PlaylistButtonActionListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            try
            {
                JFileChooser fc = new JFileChooser();

                FileFilter filter = new FileNameExtensionFilter(resourceBundle.getString("Supported_Playlists"), "wpl", "m3u", "m3u8", "xml", "pls");
                fc.setFileFilter(filter);

                int returnVal = fc.showOpenDialog(frame);

                if (returnVal == JFileChooser.APPROVE_OPTION)
                {
                    playlistField.setBackground(Color.WHITE);
                    String playlistPath = fc.getSelectedFile().getAbsolutePath();
                    playlistField.setText(playlistPath);

                    PlaylistImporter importer = new PlaylistImporter(exceptionHandler);
                    ArrayList<Media> medias = null;

                    if (playlistPath.toLowerCase().endsWith(".wpl"))
                    {
                        medias = importer.importWPLList(playlistField.getText());
                    }
                    else if (playlistField.getText().toLowerCase().endsWith(".m3u") || playlistField.getText().toLowerCase().endsWith(".m3u8"))
                    {
                        medias = importer.importM3UList(playlistField.getText());
                    }
                    else if (playlistField.getText().toLowerCase().endsWith(".xml"))
                    {
                        medias = importer.importITunesXmlList(playlistField.getText());
                    }
                    else if (playlistField.getText().toLowerCase().endsWith(".pls"))
                    {
                        medias = importer.importPLSList(playlistField.getText());
                    }

                    for (int i = tableModel.getRowCount() - 1; i > -1; i--)
                    {
                        tableModel.removeRow(i);
                    }

                    for (int i = 0; i < medias.size(); i++)
                    {
                        Object[] objectArray = {new Boolean(true), medias.get(i)};
                        tableModel.addRow(objectArray);
                    }
                }
            }
            catch (Exception ex)
            {
                exceptionHandler.handleException(ex);
            }
        }
    }

    static class FileChooserButtonActionListener implements ActionListener
    {
        private JTextField field;

        FileChooserButtonActionListener(JTextField pField)
        {
            field = pField;
        }

        public void actionPerformed(ActionEvent e)
        {
            JFileChooser fc = new JFileChooser();
            fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            int returnVal = fc.showOpenDialog(frame);

            if (returnVal == JFileChooser.APPROVE_OPTION)
            {
                field.setBackground(Color.WHITE);
                field.setText(fc.getSelectedFile().getAbsolutePath());
            }
        }
    }

    static class StartButtonActionListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            if (!outputField.getText().isEmpty() && !playlistField.getText().isEmpty())
            {
                new Thread()
                {
                    public void run()
                    {
                        try
                        {
                            FileCopier fileCopier = new FileCopier(exceptionHandler);
                            ArrayList<Media> selectedMedias = new ArrayList<Media>();

                            for (int row = 0; row < table.getRowCount(); row++)
                            {
                                Media media = (Media) tableModel.getValueAt(row, 1);

                                if ((Boolean) tableModel.getValueAt(row, 0))
                                {
                                    selectedMedias.add(media);
                                }
                            }

                            progressBar.setValue(0);
                            progressBar.setMaximum(selectedMedias.size());

                            for (int i = 0; i < selectedMedias.size(); i++)
                            {
                                Media media = selectedMedias.get(i);
                                File mediaFile = new File(media.getPath());
                                fileCopier.copyFile(mediaFile, new File(outputField.getText() + "/" + mediaFile.getName()));
                                progressBar.setValue(i);
                            }

                            progressBar.setValue(progressBar.getMaximum());
                        }
                        catch (Exception ex)
                        {
                            exceptionHandler.handleException(ex);
                        }
                    }
                }.start();
            }
            else
            {
                if (outputField.getText().isEmpty())
                {
                    outputField.setBackground(Constants.LIGHT_RED);
                }

                if (playlistField.getText().isEmpty())
                {
                    playlistField.setBackground(Constants.LIGHT_RED);
                }
            }
        }
    }

    static class PlaylistExtractorTableModel extends DefaultTableModel
    {
        PlaylistExtractorTableModel(int pRowCount, int pColumnCount)
        {
            super(pRowCount, pColumnCount);
        }

        public boolean isCellEditable(int pRow, int pColumn)
        {
            return pColumn == 0;
        }

        public Class<?> getColumnClass(int column)
        {
            if (column == 0)
            {
                return Boolean.class;
            }

            return super.getColumnClass(column);
        }
    }

    static class PlaylistExtractorTableCellRenderer extends DefaultTableCellRenderer
    {
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
        {
            if (isSelected)
            {
                setForeground(table.getSelectionForeground());
                setBackground(table.getSelectionBackground());
            }
            else
            {
                setForeground(Color.BLACK);

                if ((row % 2) == 0)
                {
                    setBackground(Constants.TABLE_BLUE);
                }
                else
                {
                    setBackground(Color.WHITE);
                }
            }

            if (value.getClass().equals(Media.class))
            {
                setText(value.toString());
            }

            return this;
        }
    }

    static class BooleanCellEditor extends DefaultCellEditor
    {
        public BooleanCellEditor()
        {
            super(new JCheckBox());
            JCheckBox checkBox = (JCheckBox) getComponent();
            checkBox.setHorizontalAlignment(JCheckBox.CENTER);
        }
    }

    static class BooleanCellRenderer extends JCheckBox implements TableCellRenderer
    {

        public BooleanCellRenderer()
        {
            super();
            setHorizontalAlignment(JLabel.CENTER);
        }

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
        {
            if (isSelected)
            {
                setForeground(table.getSelectionForeground());
                setBackground(table.getSelectionBackground());
            }
            else
            {
                setForeground(table.getForeground());

                if ((row % 2) == 0)
                {
                    setBackground(Constants.TABLE_BLUE);
                }
                else
                {
                    setBackground(Color.WHITE);
                }
            }

            setSelected((value != null && ((Boolean) value).booleanValue()));
            return this;
        }
    }
}
